// locutor
// (c) 2008-2009, Normen Müller, normen.mueller@gmail.com  
// $Id$
package locutor.model.grgen.parsing

import collection.mutable.HashSet

/** 
 * @author <a href="mailto:normen.mueller@googlemail.com">Normen M&#xFC;ller</a>
 * @version 0.0.2 */
private [grgen] object ExprParser {
  
  val reserved = new HashSet[String] ++ List(
    "int", "float", "double", "string", "true", "false", "null", "typeof"
  )
  
  val delimiters = new HashSet[String] ++ List(
    "(", ")",
    ".", "::", ":",
    "?", "!",
    "+", "-", "*", "/", "%", "~",
    "^", "&&", "||", "&", "|",
    "<=", "<<", "<", "==", "!=", ">=", ">>>", ">>", ">"     
  )
  
}

/** 
 * @author <a href="mailto:normen.mueller@googlemail.com">Normen M&#xFC;ller</a>
 * @version 0.0.2 */
private [grgen] trait ExprParser extends BaseParser {
  
  def expr = bool_expr | int_expr | float_expr | string_expr | primary_expr
  
  def bool_expr: Parser[Any] = 
    ( opt("!") ~ primary_expr ~ (("?" ~ bool_expr ~ ":" ~ bool_expr | bin_bool_operator ~ bool_expr)*)
    | expr ~ compare_operator ~ expr
    | type_expr ~ compare_operator ~ type_expr
    )
  
  def int_expr: Parser[Any] =
    ( opt("+" | "-" | "~") ~ primary_expr ~ ((bin_int_operator ~ int_expr)*)
    | bool_expr ~ "?" ~ int_expr ~ ":" ~ int_expr   
    )  
  
  def float_expr: Parser[Any] =
    ( opt("+" | "-") ~ primary_expr ~ ((bin_float_operator ~ int_expr)*)
    | bool_expr ~ "?" ~ float_expr ~ ":" ~ float_expr
    )
  
  def string_expr: Parser[Any] = primary_expr ~ (("+" ~ string_expr)*)
  
  def primary_expr: Parser[Any] =
    ( ("(" ~> ("int" | "float" | "double" | "string")) ~ (")" ~> primary_expr)
    | "(" ~ expr ~ ")"
    | ident ~ opt("." ~ ident | "::" ~ ident)
    | numeric
    | string
    | "true"
    | "false"
    | "null"      
    )
  
  def type_expr = (ident | "typeof" ~ "(" ~ ident ~ ")")
  
  def compare_operator = "<=" | "<" | "==" | "!=" | ">=" | ">"
  
  def bin_bool_operator = "^" | "&&" | "||" | "&" | "|"
  
  def bin_int_operator = ("^" | "&" | "|" | "<<" | ">>>" | ">>" | "+" | "-" | "*" | "/" | "%")
  
  def bin_float_operator = "+" | "-" | "*" | "/" | "%"
}
